package com.yantong.quartz.job;

import com.yantong.pojo.Centre;
import com.yantong.service.CentreService;
import com.yantong.utils.DateUtils;
import com.yantong.pojo.Achieve;
import com.yantong.pojo.AchieveFlow;
import com.yantong.mapper.AchieveFlowMapper;
import com.yantong.mapper.AchieveMapper;
import com.yantong.service.AchieveFlowService;
import com.yantong.mapper.OrderMapper;
import com.yantong.pojo.TradeConfig;
import com.yantong.service.ConfigService;
import com.yantong.pojo.AchieveConfig;
import com.yantong.service.AchieveConfigService;
import com.yantong.pojo.Member;
import com.yantong.service.MemberService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 业绩计算定时任务
 *
 * @author kanghaixin
 * @date 2018/9/20.15:35
 */
@Service
public class AchieveTimer {
    private static final Logger logger = LoggerFactory.getLogger(AchieveTimer.class);

    @Autowired
    private CentreService centreService;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private AchieveFlowService achieveFlowService;
    @Autowired
    private AchieveFlowMapper achieveFlowMapper;
    @Autowired
    private MemberService memberService;
    @Autowired
    private ConfigService configService;
    @Autowired
    private AchieveConfigService achieveConfigService;
    @Autowired
    private AchieveMapper achieveMapper;

    private boolean taskOn = true;
    /**
     * 当天业绩流水计算
     */
    @Scheduled(cron = "0 0 1 * * ?")
    public void calcAchieveFlow() {
        if (!taskOn) {
            logger.info("system task set off!calcAchieveFlow!");
            return;
        }
        logger.info("....calcAchieveFlow start....");
        List<Centre> list = centreService.listAllCentres();
        if (CollectionUtils.isEmpty(list)) {
            logger.info("not found centre!");
            return;
        }
        int index = 1, size = 200;
        for (Centre centre : list) {
            if (centre == null || centre.getCentreId() == null) {
                logger.info("centre info error!name:{}", centre.getName());
                continue;
            }
            int startH = 20, startM = 30, endH = 20, endM = 0;
            TradeConfig config = configService.getTradeConfig(centre.getCentreId());
            if (config != null) {
                startH = config.getNodeHour() == null ? startH : config.getNodeHour();
                startM = config.getNodeMin() == null ? startM : config.getNodeMin();
                endH = config.getFreeEndHour() == null ? endH : config.getFreeEndHour();
                endM = config.getFreeEndMin() == null ? endM : config.getFreeEndMin();
            }
            Date start = DateUtils.getAppointTime(DateUtils.getAddDayDate(new Date(), -1), startH, startM);
            Date end = DateUtils.getAppointTime(new Date(), endH, endM);
            logger.info("calcAchieve start,check time:{}-{}", DateUtils.formatFull(start), DateUtils.formatFull(end));

            index = 1;
            while (true) {
                List<AchieveFlow> flows = orderMapper.getAchieveFlowBase(centre.getCentreId(), start, end, new RowBounds((index - 1) * size, size));
                if (CollectionUtils.isEmpty(flows)) {
                    logger.info("centre:{},all team achieve flow count over!", centre.getName());
                    break;
                }
                for (AchieveFlow flow : flows) {
                    /**当前门店ID**/
                    Long mid = flow.getMid();
                    if (mid == null) {
                        continue;
                    }
                    int total = flow.getPersonalOrder();
                    BigDecimal amount = flow.getPersonalAmount();
                    AchieveFlow dbInfo = achieveFlowService.getByMidAndDate(mid, start);
                    if (dbInfo == null) {
                        dbInfo = new AchieveFlow();
                        dbInfo.setMid(mid);
                        dbInfo.setPersonalOrder(flow.getPersonalOrder());
                        dbInfo.setPersonalAmount(flow.getPersonalAmount());
                        dbInfo.setAchieveDate(start);
                        dbInfo.setOrderTotal(total);
                        dbInfo.setAmountTotal(amount);
                        dbInfo.setCentreId(centre.getCentreId());
                        achieveFlowMapper.insertSelective(dbInfo);
                    } else {
                        dbInfo.setPersonalOrder(flow.getPersonalOrder());
                        dbInfo.setPersonalAmount(flow.getPersonalAmount());
                        achieveFlowMapper.updateByPrimaryKeySelective(dbInfo);
                    }
                    Member teamer = memberService.getByKey(mid);
                    calcLevel(teamer, total, amount, start);
                }
                index++;
            }
        }
        logger.info("....calcAchieveFlow end....");

    }

    /**
     * 递归算上级业绩流水
     *
     * @param teamer
     * @param total
     * @param amount
     * @param start
     */
    private void calcLevel(Member teamer, int total, BigDecimal amount, Date start) {
        if (teamer != null && teamer.getUpTeamid() != null) {
            Long upTeamId = teamer.getUpTeamid();
            AchieveFlow upFlow = achieveFlowService.getByMidAndDate(upTeamId, start);
            if (upFlow == null) {
                upFlow = new AchieveFlow();
                upFlow.setMid(upTeamId);
                upFlow.setAchieveDate(start);
                upFlow.setOrderTotal(total);
                upFlow.setAmountTotal(amount);
                upFlow.setCentreId(teamer.getCentreId());
                achieveFlowMapper.insertSelective(upFlow);
            } else {
                upFlow.setOrderTotal(upFlow.getOrderTotal() + total);
                upFlow.setAmountTotal(upFlow.getAmountTotal().add(amount));
                achieveFlowMapper.updateByPrimaryKeySelective(upFlow);
            }
            Member up = memberService.getByKey(upTeamId);
            calcLevel(up, total, amount, start);
        } else {
            logger.info("not found team leader, or this leader have't up team");
        }
    }


    /**
     * 门店业绩计算
     */
    @Scheduled(cron = "0 0 1 1 * ?")
    public void countAchieve() {
        if (!taskOn) {
            logger.info("system task set off!countAchieve!");
            return;
        }
        logger.info("countAchieve start...");
        Date start = DateUtils.getPreMonthStart();
        Date end = DateUtils.getPreMonthEnd();

        List<Centre> list = centreService.listAllCentres();
        if (CollectionUtils.isEmpty(list)) {
            logger.info("not found centre!");
            return;
        }

        int index = 1, size = 200;
        /**不同商户统计**/
        for (Centre centre : list) {
            Long centreId = centre.getCentreId();
            int min = achieveConfigService.getMinimal(centreId);
            if (min == 0) {
                logger.info("achieve config is null,centreId:{}", centreId);
                continue;
            }
            index = 1;
            while (true) {
                /**查询**/
                List<Achieve> al = achieveFlowService.countAchieve(centreId, null, start, end, (index - 1) * size, size);
                if (CollectionUtils.isEmpty(al)) {
                    logger.info("countAchieve over");
                    break;
                }
                for (Achieve achieve : al) {
                    if (achieve == null || achieve.getOrderTotal() < min) {
                        logger.info("mid:{},month:{}, total:{},lt min:{}", achieve.getMid(), achieve.getMonth(), achieve.getOrderTotal(), min);
                        continue;
                    }
                    calcAchieve(achieve, start, end, min);
                }
                index++;
            }
        }
        logger.info("countAchieve end...");
    }

    private void calcAchieve(Achieve achieve, Date start, Date end, Integer min) {
        AchieveConfig config = achieveConfigService.getByOrderNum(achieve.getCentreId(), achieve.getOrderTotal());
        if (config == null) {
            logger.info("not found config by centreId:{},total:{}", achieve.getCentreId(), achieve.getOrderTotal());
            return;
        }
        BigDecimal commission = config.getRate().multiply(BigDecimal.valueOf(achieve.getOrderTotal()));

        Long mid = achieve.getMid();
        int index = 1, size = 200;
        while (true) {
            List<Achieve> list = achieveFlowService.countAchieve(achieve.getCentreId(), mid, start, end, (index - 1) * size, size);
            if (CollectionUtils.isEmpty(list)) {
                break;
            }
            for (Achieve ae : list) {
                if (ae == null) {
                    continue;
                }
                if (ae.getOrderTotal() < min) {
                    logger.info("achieve order total:{}, lt min config! no commission!", ae.getOrderTotal());
                    continue;
                }
                AchieveConfig cg = achieveConfigService.getByOrderNum(ae.getCentreId(), ae.getOrderTotal());
                if (cg == null) {
                    logger.info("not found config by centreId:{},total:{}", ae.getCentreId(), ae.getOrderTotal());
                    continue;
                }
                BigDecimal cn = cg.getRate().multiply(BigDecimal.valueOf(ae.getOrderTotal()));
                commission = commission.subtract(cn);
                calcAchieve(ae, start, end, min);
            }
            index++;
        }
        achieve.setRemark(String.valueOf(config.getRate()));
        achieve.setCommission(commission);
        achieveMapper.insertSelective(achieve);
    }


}
